/**
 * BeanMapTests
 *
 * @author Chris Pratt
 *
 * 11/11/2011
 */
package com.anodyzed.onyx.bean;

import com.anodyzed.onyx.log.LogBuilder;
import com.anodyzed.onyx.log.sysout.SysOutLogFactory;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.EnumMap;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static org.junit.Assert.*;
import org.junit.BeforeClass;
import org.junit.Test;

public class BeanMapTests {

  /**
   * Setup the Test Harness
   */
  @BeforeClass
  public static void setup () {
    LogBuilder.setLogFactory(new SysOutLogFactory());
  } //setup

  /**
   * Perform a jUnit Test on the BeanMap get capability
   */
  @Test public void testGet () {
    Date dob = new GregorianCalendar(1955,Calendar.APRIL,1).getTime();
    Name name = new Name("John","Xavior","Doe");
    Person person = new Person(42,name,dob,"john.doe@anonymous.org",true);
    List<Integer> list = new ArrayList<Integer>();
    list.add(7);
    list.add(13);
    list.add(31);
    person.setList(list);
    Map<Position,Name> map = new EnumMap<Position,Name>(Position.class);
    map.put(Position.First,name);
    map.put(Position.Second,new Name("Jane","Xaviera","Doe"));
    person.setMap(map);
    Map<String,String> strings = new HashMap<String,String>();
    strings.put("one","One");
    strings.put("two","Two");
    strings.put("three","Three");
    person.setStrings(strings);
    Map<String,Object> personMap = new BeanMap(person);
    assertEquals(42,personMap.get("id"));
    assertEquals("John",personMap.get("name.firstname"));
    assertEquals("Doe",personMap.get("name.lastname"));
    assertEquals(dob,personMap.get("birthdate"));
    assertEquals("john.doe@anonymous.org",personMap.get("email"));
    assertTrue((Boolean)personMap.get("admin"));
    assertEquals(13,personMap.get("list[1]"));
    assertEquals("Jane",personMap.get("map[Second].firstname"));
    assertEquals("Two",personMap.get("strings[two]"));
  } //testGet

  /**
   * Perform a jUnit Test on the BeanMap put capability
   */
  @Test public void testPut () {
    Date dob = new GregorianCalendar(1955,Calendar.APRIL,1).getTime();
    Person person = new Person();
    Map<String,Object> personMap = new BeanMap(person);

    personMap.put("id",42);
    personMap.put("name.firstname","John");
    personMap.put("name.middlename","Xavior");
    personMap.put("name.lastname","Doe");
    personMap.put("birthdate",dob);
    personMap.put("email","john.doe@anonymous.org");
    personMap.put("admin",true);
    personMap.put("list[0]",7);
    personMap.put("list[1]",13);
    personMap.put("map[Second].firstname","Jane");
    personMap.put("map[Second].middlename","Xaviera");
    personMap.put("map[Second].lastname","Doe");
    personMap.put("strings[one]","One");
    personMap.put("strings[two]","Two");
    personMap.put("strings[three]","Three");

    assertEquals(42,person.getId());
    Name name = person.getName();
    assertNotNull("Name",name);
    assertEquals("John",name.getFirstname());
    assertEquals("Doe",name.getLastname());
    assertEquals(dob,person.getBirthdate());
    assertEquals("john.doe@anonymous.org",person.getEmail());
    assertTrue(person.isAdmin());
    assertEquals(13,person.getList().get(1).intValue());
    assertEquals("Jane",person.getMap().get(Position.Second).getFirstname());
    assertEquals("Two",person.getStrings().get("two"));
  } //testPut

  /**
   * jUnit 3.x Test Suite
   *
   * @return Adapted Test Suite
   */
  public static junit.framework.Test suite () {
    return new junit.framework.JUnit4TestAdapter(BeanMapTests.class);
  } //suite

} //*BeanMapTests

enum Position {
  First, Second, Third;
}

/**
 * Name
 */
@SuppressWarnings("serial")
class Name implements Serializable {
  private String firstname;
  private String lastname;
  private String middlename;
  
  /**
   * No-arg Bean Constructor
   */
  public Name () {
  } //Name

  /**
   * Constructor
   *
   * @param firstname Given Name 
   * @param middlename Alternate Name 
   * @param lastname Surname 
   */
  public Name (String firstname,String middlename,String lastname) {
    this.firstname = firstname;
    this.middlename = middlename;
    this.lastname = lastname;
  } //Name

  /**
   * Get the value of the firstname attribute. 
   *
   * @return The firstname value as a String
   */
  public String getFirstname () {
    return firstname;
  } //getFirstname
  
  /**
   * Set the value of the firstname attribute.
   *
   * @param firstname The new firstname value as a String
   */
  public void setFirstname (String firstname) {
    this.firstname = firstname;
  } //setFirstname

  /**
   * Get the value of the lastname attribute. 
   *
   * @return The lastname value as a String
   */
  public String getLastname () {
    return lastname;
  } //getLastname
  
  /**
   * Set the value of the lastname attribute.
   *
   * @param lastname The new lastname value as a String
   */
  public void setLastname (String lastname) {
    this.lastname = lastname;
  } //setLastname

  /**
   * Get the value of the middlename attribute. 
   *
   * @return The middlename value as a String
   */
  public String getMiddlename () {
    return middlename;
  } //getMiddlename
  
  /**
   * Set the value of the middlename attribute.
   *
   * @param middlename The new middlename value as a String
   */
  public void setMiddlename (String middlename) {
    this.middlename = middlename;
  } //setMiddlename

} //*Name

/**
 * Person
 */
@SuppressWarnings("serial")
class Person implements Serializable {
  private int id;
  private Name name;
  private Date birthdate;
  private String email;
  private boolean admin;
  private List<Integer> list;
  private Map<Position,Name> map;
  private Map<String,String> strings;
  
  /**
   * No-arg Bean Constructor
   */
  public Person () {
    list = new ArrayList<Integer>();
    map = new EnumMap<Position,Name>(Position.class);
    strings = new HashMap<String,String>();
  } //Person

  /**
   * Constructor
   *
   * @param id The Person Identifier 
   * @param name The Person's Name 
   * @param birthdate The Date of Birth 
   * @param email The Person's Electronic Mail Address 
   * @param admin true if the Person is an Administrator 
   */
  public Person (int id,Name name,Date birthdate,String email,boolean admin) {
    this();
    this.id = id;
    this.name = name;
    this.birthdate = birthdate;
    this.email = email;
    this.admin = admin;
  } //Person

  /**
   * Get the value of the id attribute. 
   *
   * @return The id value as a int
   */
  public int getId () {
    return id;
  } //getId
  
  /**
   * Set the value of the id attribute.
   *
   * @param id The new id value as a int
   */
  public void setId (int id) {
    this.id = id;
  } //setId

  /**
   * Get the value of the list attribute. 
   *
   * @return The list value as a List<Integer>
   */
  public List<Integer> getList () {
    return list;
  } //getList
  
  /**
   * Set the value of the list attribute.
   *
   * @param list The new list value as a List<Integer>
   */
  public void setList (List<Integer> list) {
    this.list = list;
  } //setList

  /**
   * Get the value of the map attribute. 
   *
   * @return The map value as a Map<Position,Long>
   */
  public Map<Position,Name> getMap () {
    return map;
  } //getMap
  
  /**
   * Set the value of the map attribute.
   *
   * @param map The new map value as a Map<Position,Long>
   */
  public void setMap (Map<Position,Name> map) {
    this.map = map;
  } //setMap

  /**
   * Get the value of the name attribute. 
   *
   * @return The name value as a Name
   */
  public Name getName () {
    return name;
  } //getName
  
  /**
   * Set the value of the name attribute.
   *
   * @param name The new name value as a Name
   */
  public void setName (Name name) {
    this.name = name;
  } //setName

  /**
   * Get the value of the birthdate attribute. 
   *
   * @return The birthdate value as a Date
   */
  public Date getBirthdate () {
    return birthdate;
  } //getBirthdate
  
  /**
   * Set the value of the birthdate attribute.
   *
   * @param birthdate The new birthdate value as a Date
   */
  public void setBirthdate (Date birthdate) {
    this.birthdate = birthdate;
  } //setBirthdate

  /**
   * Get the value of the email attribute. 
   *
   * @return The email value as a String
   */
  public String getEmail () {
    return email;
  } //getEmail
  
  /**
   * Set the value of the email attribute.
   *
   * @param email The new email value as a String
   */
  public void setEmail (String email) {
    this.email = email;
  } //setEmail

  /**
   * Get the value of the admin attribute. 
   *
   * @return The admin value as a boolean
   */
  public boolean isAdmin () {
    return admin;
  } //isAdmin
  
  /**
   * Set the value of the admin attribute.
   *
   * @param admin The new admin value as a boolean
   */
  public void setAdmin (boolean admin) {
    this.admin = admin;
  } //setAdmin

  /**
   * Get the value of the strings attribute. 
   *
   * @return The strings value as a Map<String,String>
   */
  public Map<String,String> getStrings () {
    return strings;
  } //getStrings
  
  /**
   * Set the value of the strings attribute.
   *
   * @param strings The new strings value as a Map<String,String>
   */
  public void setStrings (Map<String,String> strings) {
    this.strings = strings;
  } //setStrings

} //*Person

